#!/usr/bin/perl -w
# ---------------------------------------------------------------------------
# Copyright (c) 2007, Jeff Hung
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 
#  - Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#  - Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#  - Neither the name of the copyright holders nor the names of its
#    contributors may be used to endorse or promote products derived
#    from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ---------------------------------------------------------------------------

use utf8;
use strict;
use File::Basename;
use Getopt::Long;
use DBI;

my ($__exe_name__) = (basename($0));
my ($__revision__) = ('$Rev$' =~ m/(\d+)/o);
my ($__rev_date__) = ('$Date$' =~ m/(\d{4}-\d{2}-\d{2})/o);

binmode(STDOUT, ':encoding(big5)');

sub usage
{
	print STDERR <<"EOF";
Usage: $__exe_name__ [ <option> ... ] <java-file> <sq3-file>

Convert from CIN table file <cin-file> to Java source file <java-file>.

Options:

  -h,--help     Show this help messages.
  -v,--verbose  Show verbose messages.

Revision: r$__revision__ ($__rev_date__)
EOF
	exit(0);
}

sub msg_exit
{
	my $ex = ((scalar(@_) > 0) ? shift @_ : 0);
	foreach my $m (@_) {
		print STDERR "ERROR: $m\n";
	}
	print STDERR <<"EOF";
Usage: $__exe_name__ [ <option> ... ] <java-file> <sq3-file>
Type '$__exe_name__ --help' for usage.
EOF
	exit($ex);
}

my $opt_verbose = 0;
if (!GetOptions('h|help'    => sub { usage; },
                'v|verbose' => \$opt_verbose)) {
	msg_exit(0);
}
my $arg_java_file = shift @ARGV or msg_exit(1, 'Missing <java-file>.');
my @arg_cin_files = @ARGV;
(scalar(@arg_cin_files) > 0) or msg_exit(1, 'Missing <cin-file.');

open(my $javafh, '>:encoding(utf8)', $arg_java_file)
	or msg_exit(2, "Cannot open <java-file>: $arg_java_file: $!");

foreach my $cin_file (@arg_cin_files) {
	my ($cin_name, $dir, $suffix) = fileparse($cin_file, '\.cin');
	($suffix eq '.cin') or msg_exit(2, "Invalid <cin-file>: $cin_file");

	my $cin_type;
	my $cin_ename;
	my $cin_cname;
	my $cin_selkeys;
	my $cin_endkeys;
	my %cin_key2name;
	my %cin_keys2words;

	print STDERR "Parsing <cin-file>: $cin_file\n";
	open(my $fh, '<:encoding(utf8)', $cin_file)
		or msg_exit(2, "Cannot open <cin-file>: $cin_file: $!");
	my $line;
	$line = <$fh>;
	if ($line =~ m/^\%(gen_inp)/o) {
		$cin_type = $1;
	}
	else {
		msg_exit(2, "$cin_file($.): Bad <cin-file> format: missing type.");
	}
	while ($line = <$fh>) {
		chomp($line);
		if ($line =~ m/^\%ename\s+(.*)$/o) {
			$cin_ename = $1; chomp($cin_ename);
		}
		elsif ($line =~  m/^\%cname\s+(.*)$/o) {
			$cin_cname = $1; chomp($cin_cname);
		}
		elsif ($line =~ m/^\%selkey\s+(.*)$/o) {
			$cin_selkeys = $1; chomp($cin_selkeys);
		}
		elsif ($line =~ m/^\%endkey\s+(.*)$/o) {
			$cin_endkeys = $1; chomp($cin_endkeys);
		}
		elsif ($line =~ m/^\%keyname\s+begin\s*$/o) {
			while ($line = <$fh>) {
				chomp($line);
				if ($line =~ m/^\%keyname\s+end\s*$/o) {
					last; # while
				}
				elsif ($line =~ m/^([^%].*)\s+(.*)$/o) {
					my $key = $1;  chop($key);
					my $name = $2; chomp($name);
					print "keyname: '$key' => $name\n";
					$cin_key2name{$key} = $name;
				}
				else {
					msg_exit(2, "$cin_file($.): Unknown <cin-file> format: bad keyname entry.");
				}
			}
		}
		elsif ($line =~ m/^\%chardef\s+begin\s*$/o) {
			while ($line = <$fh>) {
				chomp($line);
				if ($line =~ m/^\%chardef\s+end\s*$/o) {
					last; # while
				}
				elsif ($line =~ m/^([^%].*)\s+(.*)$/o) {
					my $key = $1;  chomp($key);
					my $char = $2; chomp($char);
					if (!defined($cin_keys2words{$key})) {
						$cin_keys2words{$key} = [];
					}
					push(@{$cin_keys2words{$key}}, $char);
				}
				else {
					msg_exit(2, "$cin_file($.): Unknown <cin-file> format: bad chardef entry.");
				}
			}
		}
	}
	close($fh);
	print STDERR "Parsed <cin-file>: $cin_file\n";

	foreach my $k (keys %cin_key2name) {
		my $n = $cin_key2name{$k};
		print "$k => $n\n";
	}
#	exit;

	print STDERR "\rInserting keys2words data... ";
	my $num_inserted = 0;
	foreach my $k2w_keys (keys %cin_keys2words) {
		my $keys = '';
		for (my $i = 0; $i < length($k2w_keys); ++$i) {
			my $keyname = substr($k2w_keys, $i, 1);
#			printf "'%s' => %s\n", $keyname, $cin_key2name{$keyname};
			$keys .= $cin_key2name{$keyname};
		}
		my $k2w_words = $cin_keys2words{$k2w_keys};
		my $words = join(' ', @$k2w_words);
		print $javafh ("K2W.put(\"$keys\", \"$words\");\n");
		++$num_inserted;
		print STDERR "\rInserting keys2words data... ($num_inserted)";
	}
	print STDERR "\rInserting keys2words data... [done]                 \n";
}

close($javafh);


